package request

import (
	"context"
	"encoding/json"
	"fmt"
	"gopkg.in/yaml.v3"
	"hotgo/internal/model/input/sysin"
	"hotgo/internal/service"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"
)

type AppConfiguration struct {
	ErpInfo configStruct `yaml:"ErpInfo"`
}
type configStruct struct {
	APICERTKEY string `yaml:"APICERTKEY"`
	USERID     string `yaml:"USERID"`
	COM_CODE   string `yaml:"COM_CODE"`
}

type ErpUtils struct {
}

type ErpInfo struct {
	APICERTKEY string
	USERID     string
	COM_CODE   string
}
type ZoneStr struct {
	ZONE   string
	DOMAIN string
}

type APIResponse struct {
	Data             Data        `json:"Data"`
	Status           string      `json:"Status"`
	Errors           interface{} `json:"Errors"` // 可以根据实际类型修改为具体类型
	Error            interface{} `json:"Error"`  // 可以根据实际类型修改为具体类型
	Timestamp        string      `json:"Timestamp"`
	RequestKey       interface{} `json:"RequestKey"`
	IsEnableNoL4     bool        `json:"IsEnableNoL4"`
	RefreshTimestamp string      `json:"RefreshTimestamp"`
	AsyncActionKey   interface{} `json:"AsyncActionKey"`
}

// Data 对应返回中Data字段的结构
type Data struct {
	EXPIRE_DATE interface{} `json:"EXPIRE_DATE"`
	COM_CODE    string      `json:"COM_CODE"`
	DOMAIN      string      `json:"DOMAIN"`
	STATUS      string      `json:"STATUS"`
	ZONE        string      `json:"ZONE"`
	DB_SHARD_NO interface{} `json:"DB_SHARD_NO"`
	CS_COM_CODE string      `json:"CS_COM_CODE"`
	ACCESS_ALL  interface{} `json:"ACCESS_ALL"`
	APP_DT_FROM interface{} `json:"APP_DT_FROM"`
	APP_DT_TO   interface{} `json:"APP_DT_TO"`
	MSG         string      `json:"MSG"`
	DB_CON_FLAG string      `json:"DB_CON_FLAG"`
	EMPTY_ZONE  interface{} `json:"EMPTY_ZONE"`
	SIP         string      `json:"SIP"`
}

func getFile() AppConfiguration {
	// 读取 YAML 文件内容
	yamlFile, err := ioutil.ReadFile("manifest/config/config.yaml")
	if err != nil {
		log.Fatalf("无法读取 YAML 文件: %v", err)
	}

	// 解析 YAML 文件到 Configuration 结构体
	var config AppConfiguration
	err = yaml.Unmarshal(yamlFile, &config)
	if err != nil {
		log.Fatalf("无法解析 YAML 文件: %v", err)
	}
	return config
}

// Request 请求
func (e ErpUtils) Request(url string, payload *strings.Reader, method string) (data []byte, err error) {
	//url := "https://oapi.ecount.cn/OAPI/V2/Zone"
	//payload := strings.NewReader(`{"COM_CODE":"80001"}`)
	client := &http.Client{}
	req, err := http.NewRequest(method, url, payload)
	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Add("Content-Type", "application/json")
	//req.Header.Add("Accept", "*/*")
	//req.Header.Add("Host", "oapi.ecount.cn")
	//req.Header.Add("Connection", "keep-alive")
	//req.Header.Add("Cookie", "SVID=Login-F02_e90cb|aKbGL")
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	//fmt.Println(string(body))
	return body, nil
}

// GetZone 获取Zone接口
func (e ErpUtils) GetZone() (data []byte, err error) {
	payload := strings.NewReader(fmt.Sprintf(`{"COM_CODE":"%s"}`, getFile().ErpInfo.COM_CODE))
	data, err = e.Request("https://oapi.ecount.cn/OAPI/V2/Zone", payload, "POST")
	if err != nil {
		fmt.Println(err)
		return
	}
	return

}

type APILoginResponse struct {
	Data             DataLogin   `json:"Data"`
	Status           string      `json:"Status"`
	Errors           interface{} `json:"Errors"`
	Error            interface{} `json:"Error"`
	Timestamp        string      `json:"Timestamp"`
	RequestKey       interface{} `json:"RequestKey"`
	IsEnableNoL4     bool        `json:"IsEnableNoL4"`
	RefreshTimestamp string      `json:"RefreshTimestamp"`
	AsyncActionKey   interface{} `json:"AsyncActionKey"`
}

// Data 对应返回中Data字段的结构
type DataLogin struct {
	EXPIRE_DATE         string      `json:"EXPIRE_DATE"`
	NOTICE              string      `json:"NOTICE"`
	Code                string      `json:"Code"`
	Message             interface{} `json:"Message"`
	FailCount           interface{} `json:"FailCount"`
	RedirectUrl         interface{} `json:"RedirectUrl"`
	LoginErrcountResult interface{} `json:"LoginErrcountResult"`
	Datas               DatasLogin  `json:"Datas"`
}

// Datas 对应Data字段中的Datas嵌套结构
type DatasLogin struct {
	SESSION_ID string `json:"SESSION_ID"`
	HOST_URL   string `json:"HOST_URL"`
	SET_COOKIE string `json:"SET_COOKIE"`
	COM_CODE   string `json:"COM_CODE"`
	USER_ID    string `json:"USER_ID"`
}

// ErpLogin 调用登录接口
func (e ErpUtils) ErpLogin(ctx context.Context) {
	data, err := e.GetZone()
	jsonData := APIResponse{}
	loginData := APILoginResponse{}
	if err != nil {
		fmt.Println(err)
		return
	}
	err = json.Unmarshal(data, &jsonData)
	if err != nil {
		return
	}
	url := fmt.Sprintf("https://sboapi%s.ecount.cn/OAPI/V2/OAPILogin", jsonData.Data.ZONE) //请求URL
	//ZONE := fmt.Sprintf("%s %s", jsonData.DOMAIN, jsonData.ZONE)                      //Zone
	jsonPayload := fmt.Sprintf(`{"COM_CODE":"%s","USER_ID":"%s","API_CERT_KEY":"%s","LAN_TYPE":"zh-CN","ZONE":"%s"}`, getFile().ErpInfo.COM_CODE, getFile().ErpInfo.USERID, getFile().ErpInfo.APICERTKEY, jsonData.Data.ZONE)
	fmt.Println(jsonPayload, "jsonPayload")
	payload := strings.NewReader(jsonPayload)
	data2, err := e.Request(url, payload, "POST")
	fmt.Println(string(data2), "data2data2data2")
	err = json.Unmarshal(data2, &loginData)
	fmt.Println(loginData.Data.Datas.SESSION_ID, "loginDataloginDataloginDataSESSION_ID") //拿到SessionId
	if loginData.Data.Datas.SESSION_ID == "" {                                            //判断有无
		return
	}
	var req = &sysin.ErpInfoEditInp{}
	req.Id = 1
	req.Zone = jsonData.Data.ZONE
	req.Sessionid = loginData.Data.Datas.SESSION_ID
	req.Domain = jsonData.Data.DOMAIN
	err = service.SysErpInfo().Edit(ctx, req)
	if err != nil {
		panic(err)
	}
}

type ResponseRoot struct {
	Data             DataGetList     `json:"Data"`             // 核心数据
	Status           string          `json:"Status"`           // HTTP状态码（字符串类型）
	Errors           []GetListErrors `json:"Errors"`           // 错误信息（可能为null）
	Error            *GetListError   `json:"Error"`            // 错误信息（冗余字段，可能为null）
	Timestamp        string          `json:"Timestamp"`        // 响应时间戳
	RequestKey       interface{}     `json:"RequestKey"`       // 请求键（可能为null）
	IsEnableNoL4     bool            `json:"IsEnableNoL4"`     // 是否启用NoL4
	RefreshTimestamp string          `json:"RefreshTimestamp"` // 刷新时间戳（字符串类型）
	AsyncActionKey   interface{}     `json:"AsyncActionKey"`   // 异步操作键（可能为null）
}

// Data 核心数据结构体（对应JSON中的Data字段）
type DataGetList struct {
	IsSuccess     bool         `json:"IsSuccess"`     // 调用是否成功
	EXPIRE_DATE   string       `json:"EXPIRE_DATE"`   // 过期日期（空字符串）
	QUANTITY_INFO string       `json:"QUANTITY_INFO"` // 流量限制信息（字符串格式）
	TRACE_ID      string       `json:"TRACE_ID"`      // 追踪ID
	TotalCnt      int          `json:"TotalCnt"`      // 结果集总数
	Result        []ResultItem `json:"Result"`        // 库存数据列表（结构体切片）
}

// ResultItem 库存数据结构体（对应JSON中Result数组的元素）
type ResultItem struct {
	WH_CD         string `json:"WH_CD"`         // 仓库编码
	WH_DES        string `json:"WH_DES"`        // 仓库描述
	PROD_CD       string `json:"PROD_CD"`       // 产品编码
	PROD_DES      string `json:"PROD_DES"`      // 产品描述
	PROD_SIZE_DES string `json:"PROD_SIZE_DES"` // 产品规格描述
	BAL_QTY       string `json:"BAL_QTY"`       // 库存数量（字符串格式的数字）
}

type GetListErrors struct {
	ProgramId string      `json:"ProgramId"`
	Name      string      `json:"Name"`
	Code      string      `json:"Code"`
	Message   string      `json:"Message"`
	Param     interface{} `json:"Param"`
}
type GetListError struct {
	Code          int    `json:"Code"`
	Message       string `json:"Message"`
	MessageDetail string `json:"MessageDetail"`
}

// （可选）流量限制信息结构体：用于解析QUANTITY_INFO字段
type QuantityInfo struct {
	HourlyErrorLimit int // 每小时连续错误限制件数（0/30）
	HourlyAllowance  int // 1小时允许量（8/6000）
	DailyAllowance   int // 1日允许量（8/10000）
}

// GetListInventoryBalanceStatusByLocation 按仓库库存报表
func (e ErpUtils) GetListInventoryBalanceStatusByLocation(ctx context.Context, data string) (getList *ResponseRoot, err error) {
	var req = &sysin.ErpInfoViewInp{}
	req.Id = 1
	view, err := service.SysErpInfo().View(ctx, req)
	if err != nil {
		return
	}
	// 获取当前时间
	now := time.Now()

	// 定义一个格式化的模板，这里我们不需要分隔符
	const layout = "20060102" // 注意这里的数字要和下面的格式对应
	// 使用Format方法按照指定的格式生成字符串
	date := now.Format(layout)
	jsonPayload := fmt.Sprintf(`{"SESSION_ID":"%s","BASE_DATE":"%s","WH_CD":"%s","DEL_LOCATION_YN":'Y',"DEL_GUBUN":'Y',"BAL_FLAG":'Y'}`, view.Sessionid, date, data)
	fmt.Println(jsonPayload, "jsonPayload")
	payload := strings.NewReader(jsonPayload)
	url := fmt.Sprintf("https://sboapi%s.ecount.cn/OAPI/V2/InventoryBalance/GetListInventoryBalanceStatusByLocation?SESSION_ID=%s", view.Zone, view.Sessionid)
	fmt.Println(url, "urlurlurlurlurl")
	JsonGetListInventory, err := e.Request(url, payload, "POST")
	if err != nil {
		panic(err)
		return nil, err
	}

	getList = &ResponseRoot{}
	err = json.Unmarshal(JsonGetListInventory, getList)
	if err != nil {
		return nil, err
	}
	if getList.Error != nil {
		fmt.Println("Error报错了")
		e.ErpLogin(ctx)
		list, err := e.GetListInventoryBalanceStatusByLocation(ctx, data)
		return list, err
	}
	fmt.Println(getList, "getListgetListgetListgetList")
	return
	//TODO: 去掉
	//deduplicatedObjects := DeduplicateToDTO(getList.Data.Result)
	//return deduplicatedObjects, nil
}

// 2. 关键：去重后的目标对象结构体（键值对形式）
// WarehouseDTO：最终要返回的对象，仅保留需要的键值对
type WarehouseDTO struct {
	WH_CD  string `json:"WH_CD"`  // 仓库编码（键）
	WH_DES string `json:"WH_DES"` // 仓库描述（键）
}

// 3. 核心去重函数：返回 WarehouseDTO 切片（对象数组）
// DeduplicateToDTO：以 WH_CD（第0位）去重，返回键值对对象数组
func DeduplicateToDTO(result []ResultItem) []WarehouseDTO {
	// map 去重：key=WH_CD（唯一），value=WarehouseDTO（避免重复）
	uniqueWarehouseMap := make(map[string]WarehouseDTO)

	// 遍历原始 Result 数组，按 WH_CD 去重
	for _, item := range result {
		// 过滤无效数据（可选：若 WH_CD 为空，跳过）
		fmt.Println(item.WH_CD, "item.WH_CD")
		if item.WH_CD == "" {
			continue
		}
		// 若 WH_CD 未存在于 map，添加到 map
		if _, exists := uniqueWarehouseMap[item.WH_CD]; !exists {
			uniqueWarehouseMap[item.WH_CD] = WarehouseDTO{
				WH_CD:  item.WH_CD,  // 保留原始仓库编码
				WH_DES: item.WH_DES, // 保留对应仓库描述
			}
		}
	}

	// 将 map 转为 WarehouseDTO 切片（对象数组）
	var deduplicatedDTOs []WarehouseDTO
	for _, dto := range uniqueWarehouseMap {
		deduplicatedDTOs = append(deduplicatedDTOs, dto)
	}

	return deduplicatedDTOs
}

type StoreRes struct {
	Code int      `json:"code"`
	Msg  string   `json:"msg"`
	Data *[]Store `json:"data"`
}
type Store struct {
	ID           int     `json:"id"`           // 唯一标识
	Mobile       string  `json:"mobile"`       // 联系电话
	Province     int     `json:"province"`     // 省份编码
	City         int     `json:"city"`         // 城市编码
	Area         int     `json:"area"`         // 区县编码
	Status       string  `json:"status"`       // 状态（如"1"）
	Name         string  `json:"name"`         // 门店名称
	Address      string  `json:"address"`      // 门店地址
	ContactsName string  `json:"contactsName"` // 联系人姓名
	Add          *string `json:"add"`          // 预留字段（null用指针接收）
}

func (e ErpUtils) GetSYUserInfo(ctx context.Context) (storeList *[]Store, err error) {
	url := "http://113.44.251.164:8081/api/merchants"
	payload := strings.NewReader("")
	data, err := e.Request(url, payload, "GET")
	if err != nil {
		return
	}
	fmt.Println(string(data), "(strings)")
	storeLsts := &StoreRes{}
	err = json.Unmarshal(data, storeLsts)
	if err != nil {
		return nil, err
	}
	if storeLsts.Code != 200 {
		return nil, err
	}
	storeList = storeLsts.Data
	return
}
